#!/bin/bash
# hisi_l0_mem_pool_module_param_test.sh
# Test script for validating hisi_l0_mem_pool module parameter values

# Script configuration
MODULE_NAME="hisi_l0_mem_pool"
TEST_DIR="/tmp/hisi_l0_mem_pool_test"
LOG_FILE="${TEST_DIR}/test_results.log"
DRIVER_PATH="./hisi_l0_mem_pool.ko"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Test result counters
PASSED=0
FAILED=0
TOTAL=0

# Create test directory
mkdir -p ${TEST_DIR}

# Logging functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1" | tee -a ${LOG_FILE}
}

log_pass() {
    echo -e "${GREEN}[PASS]${NC} $1" | tee -a ${LOG_FILE}
    ((PASSED++))
    ((TOTAL++))
}

log_fail() {
    echo -e "${RED}[FAIL]${NC} $1" | tee -a ${LOG_FILE}
    ((FAILED++))
    ((TOTAL++))
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1" | tee -a ${LOG_FILE}
}

# Check if module is loaded and unload it
cleanup_module() {
    if lsmod | grep -q "${MODULE_NAME}"; then
        log_info "Unloading existing ${MODULE_NAME} module"
        sudo rmmod ${MODULE_NAME} 2>/dev/null
        if [ $? -eq 0 ]; then
            log_info "Successfully unloaded ${MODULE_NAME}"
        else
            log_warn "Failed to unload ${MODULE_NAME}, may still be in use"
        fi
    fi
}

# Test function to load module with specific parameters
test_module_params() {
    local test_name="$1"
    local params="$2"
    local should_pass="$3"  # 0 for should pass, 1 for should fail
    
    log_info "Testing: ${test_name}"
    log_info "Parameters: ${params}"
    
    # Clean up before test
    cleanup_module
    
    # Try to load module with parameters
    if [ -n "${params}" ]; then
        bash -c "sudo insmod ${DRIVER_PATH} ${params}" 2>/tmp/modprobe_stderr.log
    else
        sudo insmod ${DRIVER_PATH} 2>/tmp/modprobe_stderr.log
    fi
    
    local result=$?
    local stderr_output=$(cat /tmp/modprobe_stderr.log 2>/dev/null)
    
    if [ ${should_pass} -eq 0 ]; then
        # Test should pass
        if [ ${result} -eq 0 ] && lsmod | grep -q "${MODULE_NAME}"; then
            log_pass "${test_name} - Module loaded successfully"
            # Unload for next test
            sudo rmmod ${MODULE_NAME}
        else
            log_fail "${test_name} - Module failed to load. Exit code: ${result}"
            if [ -n "${stderr_output}" ]; then
                log_info "Error output: ${stderr_output}"
            fi
        fi
    else
        # Test should fail
        if [ ${result} -ne 0 ] || ! lsmod | grep -q "${MODULE_NAME}"; then
            log_pass "${test_name} - Module correctly rejected invalid parameters"
            if [ -n "${stderr_output}" ]; then
                log_info "Error output: ${stderr_output}"
            fi
        else
            log_fail "${test_name} - Module incorrectly loaded with invalid parameters"
            # Clean up
            sudo rmmod ${MODULE_NAME} 2>/dev/null
        fi
    fi
    
    # Clean up stderr log
    rm -f /tmp/modprobe_stderr.log
}

# Main test function
run_tests() {
    log_info "Starting ${MODULE_NAME} module parameter validation tests"
    log_info "Driver path: ${DRIVER_PATH}"
    log_info "Log file: ${LOG_FILE}"
    
    # Check if driver file exists
    if [ ! -f "${DRIVER_PATH}" ]; then
        log_fail "Driver file ${DRIVER_PATH} not found"
        return 1
    fi
    
    rmmod hisi_l0_mem_pool

    # Test 1: Default parameters (should pass)
    test_module_params "Default parameters" "" 0
    
    # Test 2: Valid max_numa_capacity values
    test_module_params "Valid max_numa_capacity (20)" "max_numa_capacity=20" 0
    test_module_params "Valid max_numa_capacity (100)" "max_numa_capacity=100" 0
    test_module_params "Valid max_numa_capacity (1000)" "max_numa_capacity=1000" 0
    
    # Test 3: Invalid max_numa_capacity values (should fail)
    test_module_params "Invalid max_numa_capacity (0)" "max_numa_capacity=0" 1
    test_module_params "Invalid max_numa_capacity (-1)" "max_numa_capacity=-1" 1
    
    # Test 4: Valid pre_alloc_size values
    test_module_params "Valid pre_alloc_size (0)" "max_numa_capacity=100 pre_alloc_size=0" 0
    test_module_params "Valid pre_alloc_size (10)" "max_numa_capacity=100 pre_alloc_size=10" 0
    test_module_params "Valid pre_alloc_size (50)" "max_numa_capacity=100 pre_alloc_size=50" 0
    
    # Test 5: Invalid pre_alloc_size values (should fail)
    test_module_params "Invalid pre_alloc_size (exceeds max_numa_capacity)" "max_numa_capacity=20 pre_alloc_size=50" 1
    test_module_params "Invalid pre_alloc_size (negative)" "max_numa_capacity=100 pre_alloc_size=-1" 1
    
    # Test 6: Valid preinit_cache_levels values
    test_module_params "Valid preinit_cache_levels (0x00)" "preinit_cache_levels=0x00" 0
    test_module_params "Valid preinit_cache_levels (0x0F)" "preinit_cache_levels=0x0F" 0
    test_module_params "Valid preinit_cache_levels (0xFF)" "preinit_cache_levels=0xFF" 0
    test_module_params "Valid preinit_cache_levels (0x3FF)" "preinit_cache_levels=0x3FF" 0
    
    # Test 7: Invalid preinit_cache_levels values (should fail)
    test_module_params "Invalid preinit_cache_levels (too large)" "preinit_cache_levels=0xFFFF" 1
    test_module_params "Invalid preinit_cache_levels (negative)" "preinit_cache_levels=-1" 1
    
    # Test 8: Valid prealloc_numa_nodes values
    test_module_params "Valid prealloc_numa_nodes (empty)" "prealloc_numa_nodes=''" 0
    test_module_params "Valid prealloc_numa_nodes (single node)" "prealloc_numa_nodes='0'" 0
    test_module_params "Valid prealloc_numa_nodes (multiple nodes)" "prealloc_numa_nodes='0,1,2'" 0
    test_module_params "Valid prealloc_numa_nodes (with spaces)" "prealloc_numa_nodes='0, 1, 2'" 1
    
    # Test 9: Invalid prealloc_numa_nodes values (should fail)
    test_module_params "Invalid prealloc_numa_nodes (non-numeric)" "prealloc_numa_nodes='a,b,c'" 1
    test_module_params "Invalid prealloc_numa_nodes (negative node)" "prealloc_numa_nodes='-1,0'" 1
    test_module_params "Invalid prealloc_numa_nodes (non-numeric)" "prealloc_numa_nodes='@,#'" 1
    test_module_params "Invalid prealloc_numa_nodes (negative node)" "prealloc_numa_nodes='1,2,#,*'" 1
    
    # Test 10: Combined valid parameters
    test_module_params "Combined valid parameters" "max_numa_capacity=200 pre_alloc_size=20 preinit_cache_levels=0x0F prealloc_numa_nodes='0,1'" 0
    
    # Test 11: Boundary value tests
    test_module_params "Boundary max_numa_capacity (1)" "max_numa_capacity=1" 0
    test_module_params "Boundary pre_alloc_size (equal to max)" "max_numa_capacity=50 pre_alloc_size=50" 0
    
    # Clean up at the end
    cleanup_module
    
    # Print summary
    log_info "========================================"
    log_info "Test Summary:"
    log_info "Total tests: ${TOTAL}"
    log_info "Passed: ${PASSED}"
    log_info "Failed: ${FAILED}"
    
    if [ ${FAILED} -eq 0 ]; then
        log_pass "All tests completed successfully"
        return 0
    else
        log_fail "Some tests failed"
        return 1
    fi
}

# Function to check system prerequisites
check_prerequisites() {
    log_info "Checking prerequisites..."
    
    # Check if running as root
    if [ "$EUID" -ne 0 ] && [ "$1" != "no-root-check" ]; then
        log_warn "This script may need to run with sudo privileges for module operations"
    fi
    
    # Check if insmod/rmmod are available
    if ! command -v insmod &> /dev/null || ! command -v rmmod &> /dev/null; then
        log_fail "insmod or rmmod not found. Make sure you have kernel module tools installed."
        return 1
    fi
    
    # Check if lsmod is available
    if ! command -v lsmod &> /dev/null; then
        log_fail "lsmod not found. Make sure you have kernel module tools installed."
        return 1
    fi
    
    log_info "Prerequisites check passed"
    return 0
}

# Help function
show_help() {
    echo "Usage: $0 [OPTIONS]"
    echo "Test script for hisi_l0_mem_pool module parameters"
    echo ""
    echo "Options:"
    echo "  -h, --help          Show this help message"
    echo "  --driver-path PATH  Path to the driver .ko file (default: ./hisi_l0_mem_pool.ko)"
    echo "  --no-root-check     Skip root privilege check"
    echo ""
    echo "Examples:"
    echo "  $0                           # Run tests with default settings"
    echo "  $0 --driver-path /path/to/hisi_l0_mem_pool.ko  # Specify driver path"
    echo "  $0 --no-root-check         # Run without root check (some tests may fail)"
}

# Parse command line arguments
DRIVER_ARG_SET=0
NO_ROOT_CHECK=0

while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_help
            exit 0
            ;;
        --driver-path)
            DRIVER_PATH="$2"
            DRIVER_ARG_SET=1
            shift 2
            ;;
        --no-root-check)
            NO_ROOT_CHECK=1
            shift
            ;;
        *)
            echo "Unknown option: $1"
            show_help
            exit 1
            ;;
    esac
done

# Main execution
echo "========================================"
echo "HiSilicon L0 Memory Pool Module Parameter Test"
echo "========================================"

# Initialize log file
echo "Test started at: $(date)" > ${LOG_FILE}

# Check prerequisites
if [ ${NO_ROOT_CHECK} -eq 1 ]; then
    check_prerequisites "no-root-check"
else
    check_prerequisites
fi

if [ $? -ne 0 ]; then
    exit 1
fi

# Run tests
run_tests

# Exit with appropriate code
if [ ${FAILED} -eq 0 ]; then
    exit 0
else
    exit 1
fi